package com.vhall.component.service.redpacket.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vhall.component.dao.redpacket.RedPacketRecordMapper;
import com.vhall.component.entity.rebroadcast.RedPacketEntity;
import com.vhall.component.entity.rebroadcast.RedPacketRecordEntity;
import com.vhall.component.entity.redpacket.vo.RedPacketRecordReqVO;
import com.vhall.component.entity.redpacket.vo.RedPacketRecordsReqVO;
import com.vhall.component.entity.redpacket.vo.RedPacketRecordsRspVO;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.framework.common.utils.CollectionUtils;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.service.redpacket.common.RedpacketConstants;
import com.vhall.component.service.redpacket.service.CacheService;
import com.vhall.component.service.redpacket.service.RedPacketRecordService;
import com.vhall.component.service.redpacket.service.RedPacketService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Slf4j
@Service
public class RedPacketRecordServiceImpl implements RedPacketRecordService {
    @Autowired
    private RedPacketRecordMapper dao;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private RedPacketService packetService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private InnerPayService innerPayService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(RedPacketRecordEntity reqVo) {
        dao.insert(reqVo);
        //回调通知
        innerPayService.getRedPacketCallback(reqVo.getAppId(), reqVo.getUserId(), reqVo.getId(), reqVo.getAmount());
    }

    @Override
    public RedPacketRecordEntity getRecord(RedPacketRecordReqVO vo) {

        RedPacketEntity packet = packetService.getRowByRedPacketUuid(vo.getAppId(), vo.getRedPacketUuid());
        if (packet == null) {
            throw new BusinessException(BizErrorCode.COMP_REDPACKET_DELETE_ERROR);
        }

        LambdaQueryWrapper<RedPacketRecordEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(RedPacketRecordEntity::getRedPacketId, packet.getId())
                .eq(RedPacketRecordEntity::getUserId, vo.getThirdPartyUserId()).eq(RedPacketRecordEntity::getAppId, vo.getAppId());
        return dao.selectOne(wrapper);
    }

    @Override
    public RedPacketRecordsRspVO getRecords(RedPacketRecordsReqVO vo) {

        RedPacketRecordsRspVO result = new RedPacketRecordsRspVO();

        //根据uuid获取一条redPacket数据
        RedPacketEntity packet = packetService.getRowByRedPacketUuid(vo.getAppId(), vo.getRedPacketUuid());
        if (packet == null) {
            throw new BusinessException(BizErrorCode.COMP_REDPACKET_DELETE_ERROR);
        }

        Integer offset = (vo.getPage() - 1) * vo.getPageSize();

        Integer count = countRecords(vo.getAppId(), vo.getSourceId(), packet.getId());
        List<RedPacketRecordEntity> list = null;
        if (count > 0) {
            list = listRecords(vo.getAppId(), vo.getSourceId(), packet.getId(), offset,
                    vo.getPageSize(), vo.getOrder(), vo.getOrderType());
        }
        result.setCount(count);
        result.setList(list);
        BeanUtils.copyProperties(vo, result);

        return result;
    }

    private Integer countRecords(String appId, String sourceId, Long redPacketId) {

        QueryWrapper<RedPacketRecordEntity> where = new QueryWrapper<>();
        where.eq("app_id", appId);

        if (StringUtils.isBlank(sourceId)) {
            String key = RedpacketConstants.RED_RECORDS_ORDER_BY_AMOUNT_RANKING.replace("%s", redPacketId.toString());
            Long size = redisTemplate.opsForZSet().zCard(key);
            size = (null == size) ? 0 : size;
            if (size > 0) {
                return Integer.parseInt(size.toString());
            }
            where.eq("red_packet_id", redPacketId);
        } else {
            where.eq("room_id", sourceId);
        }
        return dao.selectCount(where);
    }

    private List<RedPacketRecordEntity> listRecords(String appId, String sourceId, Long redPacketId, Integer offset,
                                                    Integer size, String order, String orderType) {
        QueryWrapper<RedPacketRecordEntity> wrapper = new QueryWrapper<>();
        List<RedPacketRecordEntity> list = new ArrayList<>();
        wrapper.eq("app_id", appId);
        // sourceId 为空,从redis获取,packet id 对应的数据
        if (StringUtils.isBlank(sourceId)) {
            Set<String> set = cacheService.selectRedPacketRecords(redPacketId, offset, size, order, orderType);
            if (CollectionUtils.isNotEmpty(set)) {
                for (String item : set) {
                    list.add(JSON.parseObject(item, RedPacketRecordEntity.class));
                }
            }
            wrapper.eq("red_packet_id", redPacketId);
        } else {
            wrapper.eq("room_id", sourceId);
        }
        //缓存没查询到, 或者使用了 source_id 来进行统计查询
        if (CollectionUtils.isEmpty(list)) {
            wrapper.orderByAsc(order);
            wrapper.last("limit " + offset + "," + size);
            list = dao.selectList(wrapper);
        }
        return list;
    }
}
